#include <bits/stdc++.h>
using namespace std;
int n, m, m1;
int origin_array[55];
int tree_style_array[444];
int chunk_len[444];
int lazy_tag[444];
void push_up(int n)
{
	tree_style_array[n] = tree_style_array[n * 2] + tree_style_array[n * 2 + 1]; //该节点n的值是其左右儿子之和
	chunk_len[n] = chunk_len[n * 2] + chunk_len[n * 2 + 1];						 //该节点的区间长度是其左右儿子之和
}
void lazy_tag_change(int node)
{
	//懒标的作用就是处理区间操作的辅助
	//想象一下,你要把1-3区间+1
	//于是你找到了节点1-2和3并把他们+1了
	//但是当你去找2-4的区间和时却发现
	//你找到了没有被标记的节点2和节点3-4
	//结果自然错误
	//也就是说是这样一种情况
	//			1-4
	//		1-2		3-4
	//	1	2		3	4
	//你要把1-3区间+1
	//于是它变成了这样
	//			1-4(+2)
	//	1-2(+1)				3-4(+1)
	//	1	2			3(+1)	4
	//但是你要去找2-4的区间和时你找到的是这几个节点
	//			1-4
	//	  1-2(+1)				   3-4<THIS
	//	1	2<THIS				3(+1)	4
	//emmmmm你发现你找到的两个节点全都没有被标记
	//所以答案就错了
	//所以我们要采取一种策略,使得答案不会出错
	//这个策略就是懒标
	//当我们对某个区间,比如1-3进行操作时,我们就把对应的节点加上懒标
	//当我们在接下来的询问中访问到某个有懒标的区间之下(有"之下"和没有之间差异很大!)的区间时,我们把懒标下传
	//并改变对应区间的值
	//以上图为例
	//			1-4
	//	1-2				3-4
	//	1	2			3	4
	//当我们对1-3区间+1时,我们除了正常的操作之外还要加懒标
	//于是它会变成这样
	//			1-4(+1)
	//	1-2(+1)<+1>				3-4(+1)
	//	1	2			3(+1)<+1>	4
	//当我们询问2-4的区间和时,我们不可避免的要经过区间1-2,在此时,我们将懒标下传并将对应的值更改
	//于是它变成了这样
	//			1-4(+1)
	//	1-2(+1)				3-4(+1)
	//	1<+1>	2<+1>			3(+1)<+1>	4
	//现在由于懒标下传,所以节点对应的值已经得到修正,一切都清净了.
	//懒标下传
	if (lazy_tag[node] != 0)
	{
		lazy_tag[node * 2] += lazy_tag[node];
		lazy_tag[node * 2 + 1] += lazy_tag[node];
		//左右儿子的懒标都要加上父亲的懒标
		tree_style_array[node * 2] += lazy_tag[node] * chunk_len[node * 2];
		tree_style_array[node * 2 + 1] += lazy_tag[node] * chunk_len[node * 2 + 1];
		//左右儿子的值变为对应长度*父亲懒标,注意是"值"而不是"懒标"
		lazy_tag[node] = 0;
		//父亲懒标清零
	}
}
void build(int node, int l, int r)
{
	if (l == r) //如果l=r,说明这是一个叶子节点
	{
		tree_style_array[node] = origin_array[l]; //事实上,在线段树的最后一层,所有节点的值都是原数组的值
		chunk_len[node] = 1;					  //记录这个节点所对应的区间长度,显然叶子节点的长度应为一
		return;
	}
	int mid = (l + r) / 2;
	build(node * 2, l, mid);		 //建左子树
	build(node * 2 + 1, mid + 1, r); //建右子树
	push_up(node);					 //左右子树都已完工,利用左右子树计算出此点的属性,包括该区间的区间和,该区间的长度.
}
void change_simple(int node, int l, int r, int k, int num)
{
	tree_style_array[node] += num; //寻找目标点的过程相当于搜索,路径上的点都与目标点有关系,都要发生变化
	if (l == k && r == k)
		return;
	int mid = (l + r) / 2;
	if (k <= mid) //如果目标点在左区间
		change_simple(node * 2, l, mid, k, num);
	else if (k > mid) //如果目标点在右区间
		change_simple(node * 2 + 1, mid + 1, r, k, num);
}
void change_chunk(int node, int l, int r, int l2, int r2, int num)
{
	//这个函数用于进行区间修改
	//区间l-r是目前节点对应的区间左右端点,区间l2-r2是要更改的区间
	//与查找相似,只要目标区间和左儿子有交集就改左儿子,与右儿子有交集就改右儿子,两个都有就都改
	if (l == l2 && r == r2)
	{
		tree_style_array[node] += chunk_len[node] * num; //注意要乘上长度
		lazy_tag[node] += num;
		//如果这是一个终止节点,就在这里修改数据
		//懒标也要修改
		return;
	}
	int mid = (l + r) / 2;
	lazy_tag_change(node); //只要经过这个点,就把懒标下传
	if (r2 <= mid)		   //和左儿子有交集
		change_chunk(node * 2, l, mid, l2, r2, num);
	else if (l2 > mid) //和右儿子有交集
		change_chunk(node * 2 + 1, mid + 1, r, l2, r2, num);
	else //两个都有
	{
		change_chunk(node * 2, l, mid, l2, mid, num);
		change_chunk(node * 2 + 1, mid + 1, r, mid + 1, r2, num);
	}
	push_up(node); //不要忘了上传,由于该节点的儿子的值发生了改变,它影响的是所有和它有交集的区间.
				   //父亲节点显然与儿子节点有交集,所以要进行修正
				   //这个修正过程会一直持续直到根节点.
				   //在递归过程中所经过的所有区间都会受到影响,所以把它写在这里没有正确性上的错误
}
int split(int node, int l, int r, int l2, int r2)
{
	if (l == l2 && r == r2)
	{
		return tree_style_array[node];
	}
	int mid = (l + r) / 2;
	lazy_tag_change(node);
	if (r2 <= mid) //如果目标区间在左儿子里
		return split(node * 2, l, mid, l2, r2);
	else if (l2 > mid) //如果目标区间在右儿子里
		return split(node * 2 + 1, mid + 1, r, l2, r2);
	else //如果目标区间与两个儿子都有交集,将目标区间分成两半,分别搜索
		return split(node * 2, l, mid, l2, mid) + split(node * 2 + 1, mid + 1, r, mid + 1, r2);
}
int main()
{
	//线段树是这样一个结构
	//							|________|
	//						|____|		|____|
	//					  |__|  |__|   |__| |__|
	//					 || || ||  || || || || ||
	//一个长度为8的区间和(最上层)被分为左右两个长度为4的区间和
	//以此类推,一直到长度为1为止
	//也就是说,在最底层的叶子节点也是一个区间分裂的终止节点
	//也就是说,线段树事实上是一个满二叉树
	//所以用一个数组就可以存储
	scanf("%d %d %d", &n, &m, &m1);
	for (int i = 1; i <= n; i++)
		scanf("%d", &origin_array[i]);
	build(1, 1, n);				 //循环建树,在许多地方都可以用到
	for (int i = 1; i <= m; i++) //单点修改,区间查询
	{
		int opt; //=1修改,=2查询
		scanf("%d", &opt);
		if (opt == 1)
		{
			int k, num;
			scanf("%d %d", &k, &num);
			change_simple(1, 1, n, k, num);
		}
		if (opt == 2)
		{
			int l, r;
			scanf("%d %d", &l, &r);
			int ans = split(1, 1, n, l, r);
			printf("%d\n", ans);
		}
	}
	for (int i = 1; i <= m1; i++) //区间修改,区间查询
	{
		int opt; //=1修改,=2查询
		scanf("%d", &opt);
		if (opt == 1)
		{
			int l, r, num;
			scanf("%d %d %d", &l, &r, &num);
			change_chunk(1, 1, n, l, r, num);
		}
		if (opt == 2)
		{
			int l, r;
			scanf("%d %d", &l, &r);
			int ans = split(1, 1, n, l, r);
			printf("%d\n", ans);
		}
	}
	return 0;
}